home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / serial / mdm-2.000 / mdm-2 / modem.c < prev    next >
C/C++ Source or Header  |  1993-11-16  |  23KB  |  1,017 lines

  1. /*************************************************************************
  2. BBS Modem Server Package Version 2
  3. --------------------------------------------------------------------------
  4.  
  5.     Copyright (C) 1992  Anthony Rumble
  6.  
  7.     This program is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU General Public License as published by
  9.     the Free Software Foundation; either version 1, or
  10.     any later version.
  11.  
  12.     This program is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details. <copying>
  16.  
  17.     You should have received a copy of the GNU General Public License
  18.     along with this program; if not, write to the Free Software
  19.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21. --------------------------------------------------------------------------
  22. RCS Info
  23.  
  24. $Header: /home/smilie/bbs/modem/RCS/modem.c,v 2.38 1993/11/17 00:13:01 smilie Exp $
  25.  
  26. $Log: modem.c,v $
  27.  * Revision 2.38  1993/11/17  00:13:01  smilie
  28.  * fixed bug in 57600
  29.  *
  30.  * Revision 2.37  1993/11/16  11:55:00  smilie
  31.  * fixed a problem with the speed setting
  32.  *
  33.  * Revision 2.36  1993/11/16  11:41:40  smilie
  34.  * Added setgetbaud which does 57600 and 115200
  35.  *
  36.  * Revision 2.35  1993/10/10  06:53:56  smilie
  37.  * fixed a slight bug with the termentry
  38.  *
  39.  * Revision 2.34  1993/10/10  06:30:06  smilie
  40.  * fixed up the window rows
  41.  *
  42.  * Revision 2.33  1993/10/10  06:25:52  smilie
  43.  * removed ut_size unused
  44.  *
  45.  * Revision 2.32  1993/10/10  06:24:28  smilie
  46.  * fixed a few things
  47.  * added new commands and functions
  48.  *
  49.  * Revision 2.31  1993/10/10  04:59:28  smilie
  50.  * fixed a few minor things
  51.  *
  52.  * Revision 2.30  1993/09/05  05:05:08  smilie
  53.  * updated things
  54.  * bug fixes
  55.  * made more portable
  56.  * added SCO entries
  57.  *
  58.  * Revision 2.29  1993/05/10  13:27:28  smilie
  59.  * added UTMP processing
  60.  *
  61.  * Revision 2.28  1993/05/10  13:00:53  smilie
  62.  * added -p option to login
  63.  *
  64.  * Revision 2.27  1993/04/12  07:32:50  smilie
  65.  * updated and tested
  66.  *
  67.  * Revision 2.26  1993/03/28  04:02:19  smilie
  68.  * update
  69.  *
  70.  * Revision 2.25  1993/03/27  13:05:55  anthony
  71.  * update
  72.  *
  73.  * Revision 2.24  1993/03/24  13:54:50  anthony
  74.  * added support for new Linux serial drivers
  75.  *
  76.  * Revision 2.23  1993/03/24  11:00:53  anthony
  77.  * fixed up some warnings
  78.  *
  79.  * Revision 2.22  1993/02/28  19:53:01  smilie
  80.  * added some things for new tty handling
  81.  *
  82.  * Revision 2.21  1993/01/06  20:47:36  smilie
  83.  * disable fork and wait
  84.  * cleaned up a little in the code
  85.  *
  86.  * Revision 2.20  1992/12/06  06:49:16  smilie
  87.  * fixed up some int/char
  88.  *
  89.  * Revision 2.19  1992/12/06  06:43:50  smilie
  90.  * fixed a bug with LOCKED
  91.  *
  92.  * Revision 2.18  1992/10/11  08:51:14  smilie
  93.  * typo
  94.  *
  95.  * Revision 2.17  1992/10/11  08:47:49  smilie
  96.  * added ifdefs for CMGET
  97.  * fixed up carrier detection
  98.  * added carrier detect flag
  99.  * removed SETSID
  100.  *
  101.  * Revision 2.16  1992/10/10  06:00:34  smilie
  102.  * fixed some things up
  103.  *
  104.  * Revision 2.15  1992/10/10  05:43:40  smilie
  105.  * fixed up some problems waiting for conmnect
  106.  *
  107.  * Revision 2.13  1992/10/10  04:48:57  smilie
  108.  * added -V command for version
  109.  *
  110.  * Revision 2.12  1992/10/09  15:29:22  smilie
  111.  * fixed a few things up
  112.  * added carrier detect and DTR control
  113.  *
  114.  * Revision 2.11  1992/10/09  14:50:24  smilie
  115.  * fixed a few other things up
  116.  *
  117.  * Revision 2.10  1992/10/09  14:29:37  smilie
  118.  * fixed up the CR detect
  119.  *
  120.  * Revision 2.9  1992/10/09  13:23:54  smilie
  121.  * fixed up some silly warnings
  122.  *
  123.  * Revision 2.8  1992/10/09  13:18:36  smilie
  124.  * Fixed small bugs from old version
  125.  * added some new options
  126.  * added config items
  127.  *
  128.  * Revision 2.7  1992/09/05  06:28:58  smilie
  129.  * tried to fix the MNP problem
  130.  *
  131.  * Revision 2.3  1992/06/29  10:14:59  smilie
  132.  * fixed a few things
  133.  *
  134.  * Revision 2.2  1992/06/22  05:24:34  smilie
  135.  * fixed a bug with getting connect strings
  136.  *
  137.  * Revision 2.1  1992/06/22  05:20:51  smilie
  138.  * new version of modem server
  139.  *
  140. --------------------------------------------------------------------------
  141.  
  142. Command Line Parameters...
  143.  
  144. modem tty speed login
  145.  
  146. eg:
  147.  
  148. /bin/modem ttys1 2400 bbs
  149.  
  150. *************************************************************************/
  151.  
  152. /* Feature test switches */
  153. #define _POSIX_SOURCE 1
  154. #define _MODEM_C
  155.  
  156. /* System Headers */
  157. #include <stdio.h>
  158. #include <termios.h>
  159. #include <signal.h>
  160. #include <fcntl.h>
  161. #include <pwd.h>
  162. #include <unistd.h>
  163. #include <errno.h>
  164. #include <string.h>
  165. #include <strings.h>
  166. #include <sys/ioctl.h>
  167. #include <sys/stat.h>
  168. #include <paths.h>
  169. #include <stdlib.h>
  170. #include <utmp.h>
  171. #ifdef linux
  172. #include <linux/fs.h>
  173. #include <linux/tty.h>
  174. #endif
  175.  
  176. /* Local Headers */
  177. #include "modem.h"
  178.  
  179. /* Macros */
  180.  
  181. #define LOG_TTY flog("%u VMIN = %u, VTIME = %u, ICANON = %u, ISIG = %u\n", __LINE__,ti.c_cc[VMIN], ti.c_cc[VTIME], ((ti.c_lflag&ICANON) ? 1 : 0), ((ti.c_lflag&ISIG) ? 1 : 0))
  182. #define LOG_FLAGS flog("i%u o%u c%u l%u\n", ti.c_iflag, ti.c_oflag, ti.c_cflag, ti.c_lflag);
  183. #define LOG_SPEED flog("ospeed = %u ispeed = %u\n", cfgetospeed(&ti), cfgetispeed(&ti));
  184.  
  185. /* File scope variables */
  186.  
  187. static char modem_rcsid[] = "$Id: modem.c,v 2.38 1993/11/17 00:13:01 smilie Exp $";
  188. #define RCSID modem_rcsid
  189.  
  190. char mtty[128];        /* Modems full tty path */
  191. char *mlogin;        /* user to login as */
  192. char stty[8];        /* short tty name */
  193.  
  194. int modem_initialised = 0;    /* If the modem has been initialised yet */
  195.  
  196. /* External variables */
  197.  
  198. config_struct CONFIG;    /* Main CONFIG file */
  199.  
  200. /* External Functions */
  201.  
  202. /* Structures and unions */
  203.  
  204. /* Functions */
  205.  
  206. /*************************************************************************
  207.                 SETGETBAUD
  208. *************************************************************************/
  209. long setgetbaud(long s)
  210. {
  211. long baudrate = 0;
  212. struct termios tt;
  213. #ifdef DEBUG
  214. struct termios ti;
  215. #endif
  216. #ifdef linux
  217. static struct serial_struct ser_io;
  218. #endif
  219. /**/      
  220.  
  221.  
  222. tcgetattr(0, &tt);        /* Get the current mode config */
  223.  
  224. #ifdef linux
  225. if (ioctl(0, TIOCGSERIAL, &ser_io) < 0)     /* Get the Serial Info */
  226.     {
  227.     flog("ERROR: Cant get Linux Serial Info(Old Kernel?)\n");
  228.     return -1;
  229.     }
  230. #endif /*linux*/
  231.       
  232. if (s != 0)         /* If setting baudrate... */
  233.     {
  234.     #ifdef DEBUG
  235.     flog("Setting speed %u\n", s);
  236.     #endif
  237.  
  238.     switch (s) 
  239.         {
  240.         case 300:
  241.             baudrate = B300;
  242.         break;
  243.         case 1200:
  244.             baudrate = B1200;
  245.         break;
  246.         case 2400:
  247.             baudrate = B2400;
  248.         break;
  249.         case 4800:
  250.             baudrate = B4800;
  251.         break;
  252.         case 9600:
  253.             baudrate = B9600;
  254.         break;
  255.         case 19200:
  256.             baudrate = B19200;
  257.         break;
  258.         case 38400:
  259.             baudrate = B38400;
  260.             #ifdef linux
  261.             ser_io.flags &= ~ASYNC_SPD_MASK;
  262.             #endif
  263.         break;
  264.         #ifdef linux
  265.         case 57600:
  266.             baudrate = B38400;
  267.             ser_io.flags &= ~ASYNC_SPD_MASK;
  268.             ser_io.flags |= ASYNC_SPD_HI;
  269.         break;  
  270.         case 115200:
  271.             baudrate = B38400;
  272.             ser_io.flags &= ~ASYNC_SPD_MASK;
  273.             ser_io.flags |= ASYNC_SPD_VHI;
  274.         break;
  275.         #endif
  276.         default:
  277.             flog("ERROR: Bad Speed %u\n", s);
  278.             return (-1);
  279.         }
  280.  
  281.     cfsetospeed(&tt, baudrate);    /* Insert speed into tt struct */
  282.     cfsetispeed(&tt, baudrate);
  283.  
  284.     tcsetattr(0, TCSADRAIN, &tt);    /* Set the speed and others */
  285.  
  286.     #ifdef DEBUG
  287.     tcgetattr(0, &ti);
  288.     LOG_SPEED;
  289.     #endif /* DEBUG */
  290.  
  291.     #ifdef linux
  292.     if (baudrate == B38400)
  293.         if (ioctl(0, TIOCSSERIAL, &ser_io) < 0)        /* set special speed */
  294.             {
  295.             flog("ERROR: Could not set linux serial info (Old Kernel?)");
  296.             return -1;
  297.             }
  298.     #ifdef DEBUG
  299.     tcgetattr(0, &ti);
  300.     LOG_SPEED;
  301.     #endif /* DEBUG */
  302.  
  303.     #endif /*linux*/
  304.     return s;
  305.     }
  306. else
  307.     {        
  308.     #ifdef DEBUG
  309.     flog("getting speed\n");
  310.     #endif
  311.     switch (cfgetospeed(&tt)) 
  312.         {
  313.         case B300:
  314.             return (300);
  315.         case B1200:
  316.             return (1200);
  317.         case B2400:
  318.             return (2400);
  319.         case B4800:
  320.             return (4800);
  321.         case B9600:
  322.             return (9600);
  323.         case B19200:
  324.             return (19200);
  325.         case B38400:     
  326.         #ifdef linux
  327.         if (ioctl(0, TIOCGSERIAL, &ser_io) < 0) 
  328.             {
  329.             flog("ERROR: Could not retrieve linux serial info (Old kernel?)\n");
  330.             return -1;
  331.             }
  332.   
  333.         if ((ser_io.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
  334.             return 115200;
  335.         else 
  336.             if ((ser_io.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
  337.                 return 57600;
  338.             else
  339.             #endif /*linux*/
  340.                 return 38400;
  341.         }
  342.     }
  343. flog("ERROR: problem setting baud rate (%u)\n", s);
  344. return -1;       
  345. }
  346. #ifdef UTMP
  347. /************************************************************************
  348.                 UPDATE_UTMP
  349. -------------------------------------------------------------------------
  350. The utmp file holds miscellaneous information about things started by
  351. /etc/init and other system-related events. Our purpose is to update
  352. the utmp entry for the current process, in particular the process type
  353. and the tty line we are listening to. Return successfully only if the
  354. utmp file can be opened for update, and if we are able to find our
  355. entry in the utmp file.
  356. *************************************************************************/
  357. void update_utmp(char *line)
  358. {
  359. struct utmp ut;
  360. int     ut_fd;
  361. pid_t     mypid = getpid();
  362. /**/
  363.  
  364. #if defined(BSD) || defined (linux)
  365. utmpname(_PATH_UTMP);
  366. #else
  367. utmpname(UTMP_FILE);
  368. #endif
  369.  
  370. memset(&ut, 0, sizeof(ut));
  371. (void)strncpy(ut.ut_user, "LOGIN", sizeof(ut.ut_user));
  372. (void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
  373. (void)strncpy(ut.ut_id, line + 3, sizeof(ut.ut_id));
  374. (void)time(&ut.ut_time);
  375. ut.ut_type = LOGIN_PROCESS;
  376. ut.ut_pid = mypid;
  377.  
  378. pututline(&ut);
  379. endutent();
  380.  
  381. if((ut_fd = open(_PATH_WTMP, O_APPEND|O_WRONLY)) >= 0) 
  382.     {
  383.     write(ut_fd, &ut, sizeof(ut));
  384.     close(ut_fd);
  385.     }
  386. }
  387. #endif /* UTMP */
  388. /*************************************************************************
  389.                  WAIT_FOR_CR
  390. *************************************************************************/
  391. int wait_for_cr()
  392. {
  393. struct termios ti, tiold;
  394. int ch;
  395. /**/
  396. printf("Please press return to continue...\n");
  397. (void)tcgetattr(0, &ti);
  398. (void)tcgetattr(0, &tiold);
  399.  
  400. ti.c_cc[VMIN] = 0;
  401. ti.c_cc[VTIME] = CONFIG.timeout*10;        /* Wait Timeout Period */
  402. ti.c_lflag = 0;
  403. tcsetattr(0, TCSANOW, &ti);
  404.  
  405. #ifdef DEBUG
  406. flog("CONFIG.timeout = '%hu'\n", CONFIG.timeout);
  407. tcgetattr(0, &ti);
  408. LOG_TTY;
  409. #endif
  410.  
  411. ch = 0;
  412. while ((ch != 13) && (ch != -1))
  413.     {
  414.     ch = fgetc(stdin);
  415.     #ifdef DEBUG
  416.     flog("Garbage '%d'\n", ch);
  417.     #endif
  418.     }
  419.  
  420. #ifdef DEBUG
  421. flog("Ret from GETCR '%d'\n", ch);
  422. #endif
  423.     
  424. tcsetattr(0, TCSANOW, &tiold);
  425. fflush(stdout);
  426.  
  427. return ch;
  428. }
  429. /************************************************************************
  430.                 PARSE_RETS
  431. -------------------------------------------------------------------------
  432. Convert |'s in a string to Carriage Returns.
  433.  
  434. Returns a STATIC array
  435. *************************************************************************/
  436. char *parse_rets(char *instr)
  437. {
  438. static char ret_str[256];
  439. char *ss = instr;
  440. char *s = ret_str;
  441. /**/
  442. while (*ss)
  443.     {
  444.     if (*ss == '|')
  445.         *s = 13;    /* CR */
  446.     else
  447.         *s = *ss;
  448.     s++; ss++;
  449.     }
  450. return ret_str;
  451. }
  452. /*************************************************************************
  453.                 GETREAL
  454. *************************************************************************/
  455. unsigned short getreal(int in)
  456. {
  457. /**/
  458. switch(in)
  459.     {
  460.     case 300:return B300;
  461.     case 1200:return B1200;
  462.     case 2400:return B2400;
  463.     case 4800:return B4800;
  464.     case 9600:return B9600;
  465.     case 19200:return B19200;
  466.     case 38400:return B38400;
  467.     }
  468. return B2400;
  469. }
  470. /*************************************************************************
  471.                 INITIALISE_MODEM
  472. *************************************************************************/
  473. int initialise_modem()
  474. {
  475. int stop = FALSE;
  476. char instr[256];
  477. int retry = 0;  
  478. /**/
  479. #ifdef DEBUG
  480. flog("Send to modem '%s'\n", CONFIG.init);
  481. #endif
  482. fprintf(stdout, "%s", parse_rets(CONFIG.init));    /* Send INIT String */
  483. fflush(stdout);                    /* Flush TTY */
  484. while (!stop)
  485.     {
  486.     if (fgetsraw(instr, sizeof(instr), stdin, 5))    /* Get return */
  487.         {
  488.         strupr(instr);
  489.         #ifdef DEBUG
  490.         flog("[%s]\n", instr);
  491.         #endif
  492.         if (strncmp(instr, "OK", 2) == 0)
  493.             stop = TRUE;
  494.         }
  495.     else
  496.         {
  497.         retry++;
  498.         if (retry > 10)
  499.             {
  500.             flog("initialise_modem: timeout waiting for 'OK'\n");
  501.             return FALSE;
  502.             }
  503.         flog("Timeout initialising modem, retrying..\n");
  504.         #ifdef DEBUG
  505.         flog("Send to modem '%s'\n", CONFIG.init);
  506.         #endif
  507.         fprintf(stdout, "%s", parse_rets(CONFIG.init));    /* Send INIT String */
  508.         fflush(stdout);                    /* Flush TTY */
  509.         }
  510.     }
  511. return TRUE;
  512. }
  513. /************************************************************************
  514.             PARSE_MODEM_RETURN
  515. -------------------------------------------------------------------------
  516. Parses the modem return string, returning the speed
  517. and extra.
  518. *************************************************************************/
  519. int parse_modem_return(const char *str, int *spd, char *xtra)
  520. {
  521. int num;
  522. char connect_str[20];
  523. /**/
  524. if (strncasecmp(str, "NO CARRIER", 10) == 0)
  525.     return MDM_NOCARRIER;
  526. else
  527. if (strncasecmp(str, "NO ANSWER", 9) == 0)
  528.     return MDM_NOANSWER;
  529. else
  530. if (strncasecmp(str, "NO DIALTONE", 11) == 0)
  531.     return MDM_NODIALTONE;
  532. else
  533. if (strncasecmp(str, "BUSY", 4) == 0)
  534.     return MDM_BUSY;
  535. else
  536.     {
  537.     strcpy(xtra, "");
  538.     num = sscanf(str, "%s %u/%[^:]", connect_str, spd, xtra);
  539.     if (strcasecmp(connect_str, "CONNECT") == 0)
  540.         {
  541.         if (num == 1)
  542.             {
  543.             *spd = 300;
  544.             return MDM_CONNECT;
  545.             }
  546.         if (num > 1)
  547.             {
  548.             return MDM_CONNECT;
  549.             }
  550.         }
  551.     }
  552. return MDM_UNKNOWN;
  553. }
  554. /*************************************************************************
  555.                 MAP_SPEED
  556. *************************************************************************/
  557. int map_speed(const char *instr)
  558. {
  559. int ret, speed;
  560. char extra[256];
  561. /**/
  562. ret = parse_modem_return(instr, &speed, extra);
  563.  
  564. if (ret == MDM_UNKNOWN)
  565.     {
  566.     return FALSE;
  567.     }
  568. if (ret != MDM_CONNECT)        /* If we did not get a connect message reinit the modem */
  569.     {
  570.     flog("Re-Initialising modem\n");
  571.     modem_initialised = 0;
  572.     return FALSE;
  573.     }
  574.  
  575. flog("modem: CONNECT %u%s%s\n", speed, extra[0] ? "/":"", extra);
  576.  
  577. CONFIG.conspeed = speed;            /* Save ACTUAL Transfer speed */
  578.  
  579. #ifdef DEBUG
  580. if (CONFIG.locked)
  581.     flog("Modem port locked\n");
  582. else
  583.     flog("Modem port variable\n");
  584. #endif
  585. if (!CONFIG.locked)
  586.     {
  587.     switch(speed)        /* Mapping Variable speed mode to terminal speed */
  588.         {        /* This is for thoes wierd high speed modems without */
  589.         case 28800:    /* constant speed mode.. wierd.. but true.. */
  590.             speed = 38400; /* And yes.. I do have a 28.8k V.FC modem <grin> */
  591.             break;
  592.         case 26400:
  593.             speed = 38400;
  594.             break;
  595.         case 24000:
  596.             speed = 38400;
  597.             break;
  598.         case 21600:
  599.             speed = 38400;
  600.             break;
  601.         case 19200:
  602.             speed = 19200;
  603.             break;
  604.         case 14400:
  605.             speed = 19200;
  606.             break;
  607.         case 12000:
  608.             speed = 19200;
  609.             break;
  610.          case 7200:
  611.             speed = 9600;
  612.             break;
  613.         case 4800:
  614.             speed = 9600;
  615.             break;
  616.         }
  617.     CONFIG.speed = speed;
  618.     }
  619.  
  620. #ifdef DEBUG
  621. flog("DTE speed now = '%u'\n", CONFIG.speed);
  622. #endif
  623.     
  624. return TRUE;
  625. }
  626. /*************************************************************************
  627.                 MODEM_ABORT
  628. *************************************************************************/
  629. void *modem_abort(int sig)
  630. {
  631. /**/
  632. exit(1);
  633. }
  634. /*************************************************************************
  635.                    MAIN
  636. *************************************************************************/
  637. void main(int argc, char *argv[])
  638. {
  639. struct termios ti;
  640. struct termios t;
  641. struct winsize ws;
  642. char *tterm;
  643. char tmpstr[256];
  644. int fd;
  645. FILE *fh;
  646. int stop = FALSE;
  647. int flags;
  648. /**/
  649.  
  650. if (strcasecmp(argv[1], "-V") == 0)    /* Print the version string */
  651.     {
  652.     fprintf(stderr, "Linux MODEM Server version %s\nBy Anthony Rumble\n", MDMSERVER_VERSION);
  653.     fprintf(stderr, "Compiled on %s %s\n", __DATE__, __TIME__);
  654.     exit(1);
  655.     }
  656.  
  657. strcpy(stty, argv[1]);        /* Save Short TTY name */
  658.  
  659. sleep(2);            /* Wait for rubbish to clear, and DTR to affect modem */
  660.  
  661. /* Read in Command Line options */
  662.  
  663. (void)sprintf(mtty, "/dev/%s", argv[1]);    /* Find bit past the /dev */
  664. (void)sscanf(argv[2], "%u", &CONFIG.speed);    /* Read in the initial fallback speed */
  665. mlogin = argv[3];
  666.  
  667. /* Load CONFIG files */
  668. if (!load_config())
  669.     {
  670.     flog("main: ERROR loading config files\n");
  671.     exit(1);
  672.     }
  673.  
  674. /* Setup Signal Handling */
  675. (void)signal(SIGINT, SIG_IGN);
  676. (void)signal(SIGQUIT, SIG_DFL);
  677. (void)signal(SIGTERM, SIG_DFL);
  678.  
  679. setsid();    /* Become process group leader */ 
  680.  
  681. /* Open Serial TTY */
  682. #ifdef DEBUG
  683. flog("Opening '%s'\n", mtty);
  684. #endif
  685. /* Opening without blocking */
  686. while(((fd = open(mtty, O_RDWR | O_NDELAY)) < 0) && (errno == EBUSY))
  687.     {
  688.     #ifdef DEBUG
  689.     flog("'%s' is EBUSY\n", mtty);
  690.     #endif
  691.     sleep(30);    /* If the TTY is busy, sleep 30 seconds and try again */
  692.     }
  693. if (fd<0)
  694.     {
  695.     flog("main: ERROR Opening [%s] Modem Port : %s\n", mtty, strerror(errno));
  696.     exit(1);
  697.     }
  698.  
  699. if (fd > 0)
  700.     {
  701.     if (dup2(fd, 0) != 0)
  702.         {
  703.         flog("main: ERROR cannot open stdin : %s\n", strerror(errno));
  704.         exit(1);
  705.         }
  706.     }
  707.  
  708. if (dup2(fd, 1) != 1)
  709.         {
  710.         flog("main: ERROR cannot open stdout : %s\n", strerror(errno));
  711.         exit(1);
  712.         }
  713.  
  714. /* This is to hold open the device number before I open the logger device */
  715. if (dup2(open("/dev/null", O_WRONLY), 2) != 2)    /* Open NULL */
  716.     {
  717.     flog("main: ERROR opening NULL device : %s\n", strerror(errno));
  718.     }
  719.  
  720. if (fd > 0)
  721.     (void)close(fd);
  722.  
  723. #ifdef DEBUG
  724. flog("Linux MODEM Server version %s\n", MDMSERVER_VERSION);
  725. flog("Compiled on %s %s\n", __DATE__, __TIME__);
  726. #endif
  727.     
  728. /* Flush any rubbish */
  729.  
  730. tcflush(0, TCIOFLUSH);
  731.     
  732. /* Setup the terminal */
  733.  
  734. #ifdef linux
  735. t.c_cflag = CS8|CREAD|CRTSCTS|HUPCL;
  736. #else
  737. t.c_cflag = CS8|CREAD|ORTSFL|HUPCL;
  738. #endif
  739. t.c_iflag = IXON|IGNBRK|IXOFF;
  740. t.c_oflag = CR0|NL0|TAB0|BS0|FF0|VT0;
  741. t.c_lflag = ICANON;
  742.  
  743. t.c_cc[VMIN]=1;
  744. t.c_cc[VTIME]=0;
  745. t.c_cc[VEOF] = _POSIX_VDISABLE;
  746. t.c_cc[VEOL] = _POSIX_VDISABLE;
  747. t.c_cc[VERASE] = 0x08;
  748. t.c_cc[VINTR] = _POSIX_VDISABLE;
  749. t.c_cc[VKILL] = _POSIX_VDISABLE;
  750. t.c_cc[VQUIT] = _POSIX_VDISABLE;
  751. t.c_cc[VSUSP] = _POSIX_VDISABLE;
  752. t.c_cc[VSTART] = 0x11;
  753. t.c_cc[VSTOP] = 0x13;
  754.  
  755. tcsetattr(0, TCSADRAIN, &t);
  756.  
  757. /* Set proper speed */
  758. if (CONFIG.initspeed)
  759.     setgetbaud(CONFIG.initspeed);
  760. else
  761.     setgetbaud(CONFIG.speed);
  762.  
  763. tcgetattr(0, &ti);
  764.  
  765. #ifdef DEBUG
  766. flog("Modem server started\n");
  767. #endif
  768.  
  769. sleep(2);        /* Wait for things to clear */
  770. tcflush(0, TCIOFLUSH);    /* Flush any rubbish */
  771.     
  772. #ifdef DEBUG
  773. flog("Initialising modem at %u baud (%s)\n", CONFIG.speed, CONFIG.locked ? "Locked" : "Unlocked");
  774. #endif
  775.  
  776. /* Now make line block */
  777. flags = fcntl(0, F_GETFL, 0);
  778. (void)fcntl(0, F_SETFL, flags & ~O_NDELAY);
  779.  
  780. if(!modem_initialised)
  781.     {
  782.     if (!initialise_modem())
  783.         {
  784.         flog("main: \aError initialise modem\n");
  785.         exit(1);
  786.         }
  787.     sleep(1);
  788.     tcflush(0, TCIOFLUSH);
  789.     flog("Modem initialised\n");
  790.     modem_initialised = 1;
  791.     }
  792.  
  793. /* Close all the file descriptors */
  794. (void)close(0);
  795. (void)close(1);
  796. (void)close(2);
  797.  
  798. setsid();        /* Create a new session, become group leader */
  799.  
  800. #ifdef UTMP
  801. update_utmp(stty);    /* Clear the UTMP file */
  802. #endif /* UTMP */
  803.  
  804. #ifdef DEBUG
  805. flog("Re-Opening '%s'\n", mtty);
  806. #endif
  807.  
  808. /* Re-Open the device with blocking */
  809. fd = open(mtty, O_RDWR);
  810. if (fd<0)
  811.     {
  812.     flog("main: ERROR Opening [%s] Modem Port : %s\n", mtty, strerror(errno));
  813.     exit(1);
  814.     }
  815.  
  816. if (fd > 0)
  817.     {
  818.     close(0);
  819.     if (dup2(fd, 0) != 0)
  820.         {
  821.         flog("main: ERROR cannot open stdin : %s\n", strerror(errno));
  822.         exit(1);
  823.         }
  824.     }
  825.  
  826. if (dup2(fd, 1) != 1)
  827.         {
  828.         flog("main: ERROR cannot open stdout : %s\n", strerror(errno));
  829.         exit(1);
  830.         }
  831.  
  832. if (dup2(open("/dev/null", O_WRONLY), 2) != 2)    /* Open NULL */
  833.     {
  834.     flog("main: ERROR opening NULL device : %s\n", strerror(errno));
  835.     }
  836.  
  837. if (fd > 0)
  838.     (void)close(fd);
  839.  
  840. /* Flush any rubbish */
  841.  
  842. tcflush(0, TCIOFLUSH);
  843.  
  844. /* Setup the terminal */
  845. t.c_cflag = CS8|CREAD|CRTSCTS|HUPCL;
  846. t.c_iflag = IXON|IGNBRK|IXOFF;
  847. t.c_oflag = CR0|NL0|TAB0|BS0|FF0|VT0;
  848. t.c_lflag = ICANON;
  849.  
  850. t.c_cc[VEOF] = _POSIX_VDISABLE;
  851. t.c_cc[VEOL] = _POSIX_VDISABLE;
  852. t.c_cc[VERASE] = 0x08;
  853. t.c_cc[VINTR] = _POSIX_VDISABLE;
  854. t.c_cc[VKILL] = _POSIX_VDISABLE;
  855. t.c_cc[VQUIT] = _POSIX_VDISABLE;
  856. t.c_cc[VSUSP] = _POSIX_VDISABLE;
  857. t.c_cc[VSTART] = _POSIX_VDISABLE;
  858. t.c_cc[VSTOP] = _POSIX_VDISABLE;
  859.  
  860. tcsetattr(0, TCSADRAIN, &ti);
  861.  
  862. setgetbaud(CONFIG.speed);
  863.  
  864. #ifdef DEBUG
  865. tcgetattr(0, &ti);
  866. LOG_TTY;
  867. #endif
  868.  
  869. while (!stop)
  870.     {
  871. /*
  872.  * Look for a Connect String
  873.  * after a timeout give up looking and return CONNECT 2400
  874.  * NOTE: Some modems return the Connect String BEFORE they
  875.  * raise 'DCD'. In this case it would be best to bypass this
  876.  * alltogether and make the timeout 0
  877.  * The NetComm M7F Series 4 and the Avtek CD920/CD930's in later
  878.  * firmware have the command %p.. set %P1 and it will
  879.  * return the connect string after 'DCD'.
  880.  */
  881.  
  882.     if (!fgetsraw(tmpstr, sizeof(tmpstr), stdin, CONFIG.timeout_connect))
  883.         {
  884.         if (errno == EBADF)    
  885.             {
  886.             strcpy(tmpstr, "CONNECT 2400");
  887.             }
  888.         else
  889.             {
  890.             flog("Problem reading from STDIN (%s)", strerror(errno));
  891.             exit(1);
  892.             }
  893.         }
  894.  
  895.     strupr(tmpstr);                /* Make string uppercase */
  896.     #ifdef DEBUG
  897.     flog("[%s]\n", tmpstr);
  898.     #endif
  899.     if (map_speed(tmpstr))        /* Parse CONNECT string */
  900.         stop = TRUE;
  901.     }
  902.  
  903. (void)signal(SIGHUP, modem_abort);
  904. (void)signal(SIGINT, modem_abort);
  905. (void)signal(SIGQUIT, modem_abort);
  906. (void)signal(SIGTERM, modem_abort);
  907.     
  908. /* 
  909.  * Connect! Wait for MNP/LAPM rubbish to clear 
  910.  * Note.. This is only of use if you have a NON error correcting
  911.  * modem.
  912.  */
  913.  
  914. if (!CONFIG.error_correcting)
  915.     {
  916.     wait_for_cr();
  917.     }
  918.  
  919. /* Clear any extra rubbish */
  920.  
  921. tcflush(0, TCIOFLUSH);
  922.  
  923. t.c_iflag = IGNBRK|ICRNL|IXON|IXOFF;
  924. t.c_oflag = OPOST|ONLCR|NL0|CR0|TAB0|BS0|VT0|FF0;
  925. #ifdef linux
  926. t.c_lflag = ISIG|ICANON|IEXTEN|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE;
  927. t.c_cflag = CS8|HUPCL|CREAD|CRTSCTS;
  928. #else
  929. t.c_lflag = ISIG|ICANON|IEXTEN|ECHO|ECHOE|ECHOK;
  930. t.c_cflag = CS8|HUPCL|CREAD|ORTSFL;
  931. #endif
  932.  
  933. t.c_cc[VMIN]=1;
  934. t.c_cc[VTIME]=0;
  935. t.c_cc[VEOF] = 0x04;
  936. t.c_cc[VEOL] = 0x0A;
  937. t.c_cc[VERASE] = 0x08;
  938. t.c_cc[VINTR] = 0x03;
  939. t.c_cc[VKILL] = _POSIX_VDISABLE;
  940. t.c_cc[VQUIT] = _POSIX_VDISABLE;
  941. t.c_cc[VSUSP] = 0x1A;
  942. t.c_cc[VSTART] = 0x11;
  943. t.c_cc[VSTOP] = 0x13;
  944.  
  945. tcsetattr(0, TCSADRAIN, &t);
  946.  
  947. setgetbaud(CONFIG.speed);
  948.  
  949. #ifdef DEBUG
  950. flog("Get/Setting window size\n");
  951. #endif
  952.  
  953. /* get window size */
  954. ioctl(0, TIOCGWINSZ, &ws);
  955. if (ws.ws_row == 0)
  956.     ws.ws_row = CONFIG.rows;
  957. if (ws.ws_col == 0)
  958.     ws.ws_col = CONFIG.cols;
  959. ioctl(0, TIOCSWINSZ, &ws);
  960.  
  961. #ifdef DEBUG
  962. flog("Checking TERM entry\n");
  963. #endif
  964.  
  965. /* Check TERM entry */
  966. tterm = getenv("TERM");
  967. #ifdef DEBUG
  968. flog("TERM='%s'\n", tterm);
  969. #endif
  970. if ((tterm == NULL) || (strncasecmp(tterm, "dumb", 4) == 0))
  971.     {
  972.     setenv("TERM", "vt100", 1);
  973.     }
  974.  
  975. #ifdef DEBUG
  976. flog("Sending /etc/issue\n");
  977. #endif
  978.  
  979. /* Send issue */
  980. if (CONFIG.issue)
  981.     {
  982.     if ((fh = fopen("/etc/issue", "r")) != NULL)
  983.         {
  984.         while (!feof(fh))
  985.             {
  986.             fgetstr(tmpstr, sizeof(tmpstr), fh);
  987.             printf("%s\n", tmpstr);
  988.             }
  989.         fclose(fh);
  990.         }
  991.     else
  992.         {
  993.         flog("ERROR: Problem opening /etc/issue\n");
  994.         }
  995.     }
  996.  
  997. #ifdef DEBUG
  998. flog("Executing login as %s\n", mlogin);
  999. #endif
  1000.  
  1001. /* Redirect STDERR to STDIN/STDOUT */
  1002. dup2(0, 2);
  1003.  
  1004. #ifdef DEBUG
  1005. tcgetattr(0, &ti);
  1006. LOG_TTY;
  1007. LOG_FLAGS;
  1008. LOG_SPEED;
  1009. #endif
  1010.  
  1011. /* Execute login */
  1012. if (execlp("/bin/login", "-", mlogin, NULL) == -1)
  1013.     exit(1);
  1014. }
  1015.  
  1016.  
  1017.